﻿/* Copyright 2011 Michiel Fortuin
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * */

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace sharplog
{
	/// <summary>
	/// A message for the Windows Events log.
	/// </summary>
	internal class WinEventsLogMessage
	{
		public string Message;
		public EventLogEntryType type;
		public ushort EventID;
		public short Category;
		public byte[] rawData;
		public bool logThisMessage = true;
	}

	/// <summary>
	/// formats and converts to a Windows event log message. This formaters output WinEventsLogMessage.
	/// </summary>
	public class WinEventsLogFormater: Formater
	{
		/// <summary>
		/// converts Level to EventLogEntryType.
		/// </summary>
		/// <param name="level"></param>
		/// <returns></returns>
		private EventLogEntryType ConvertFromLevel(Level level)
		{
			if(level == Level.Alert)
				return EventLogEntryType.Warning;
			if(level == Level.Critical)
				return EventLogEntryType.Error;
			if (level == Level.Debug)
				return EventLogEntryType.Information;
			if (level == Level.Emergency)
				return EventLogEntryType.Error;
			if (level == Level.Error)
				return EventLogEntryType.Error;
			if (level == Level.Information)
				return EventLogEntryType.Information;
			if (level == Level.Notice)
				return EventLogEntryType.Information;
			if (level == Level.Warning)
				return EventLogEntryType.Warning;
			return EventLogEntryType.Information;
		}

		private bool _logDebugMessages = true;
		/// <summary>
		/// bool to check if it must log debug messages
		/// </summary>
		public bool LogDebugMessages
		{
			get { return _logDebugMessages; }
			set { _logDebugMessages = value; }
		}

		#region Overrides of Formater

		/// <summary>
		/// Constructs a message for sending
		/// </summary>
		/// <param name="level">The level of the message.</param>
		/// <param name="facility">The facility from where the log message originates.</param>
		/// <param name="messageID">An Id given to the message.</param>
		/// <param name="message">The message itself.</param>
		/// <returns>An object for a specifice sender.</returns>
		internal override object ConstructMessage(Level level, Facility facility, string messageID, string message)
		{
			WinEventsLogMessage m = new WinEventsLogMessage();
			if(level == Level.Debug && !this._logDebugMessages)
			{
				m.logThisMessage = false;
				return m;
			}
			m.type = ConvertFromLevel(level);
			m.Category = (short) facility;
			ushort.TryParse(messageID, out m.EventID);
			m.Message = message;
			m.rawData = null;
			return m;
		}

		#endregion
	}

	/// <summary>
	/// sends WinEventsLogMessages to the windows events log.
	/// </summary>
	public class WinEventsLogSender: Sender
	{
		private EventLog client;

		public WinEventsLogSender(string applicationName)
		{
			client = new EventLog("Application", ".", applicationName);
		}

		#region Overrides of Sender

		/// <summary>
		/// Sends a message.
		/// </summary>
		/// <param name="data">The pre-formated message from a specific formater.</param>
		internal override void SendMessage(object data)
		{
			WinEventsLogMessage m = (WinEventsLogMessage) data;
			if(m.logThisMessage)
			{
				client.WriteEntry(m.Message, m.type, m.EventID, m.Category, m.rawData);
			}
		}

		#endregion
	}
}
